package com.server.server_a10.mqttServer;

import com.alibaba.fastjson.JSON;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.core.MessageProducer;
import org.springframework.integration.mqtt.core.DefaultMqttPahoClientFactory;
import org.springframework.integration.mqtt.core.MqttPahoClientFactory;
import org.springframework.integration.mqtt.inbound.MqttPahoMessageDrivenChannelAdapter;
import org.springframework.integration.mqtt.outbound.MqttPahoMessageHandler;
import org.springframework.integration.mqtt.support.DefaultPahoMessageConverter;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandler;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


@Configuration
public class MqttConfig {
    //    注入redis的接口
    @Autowired
    private RedisTemplate redisTemplate;

    private long timestamp;
    // 订阅消息

    /**
     * 创建MqttPahoClientFactory，设置MQTT Broker连接属性，如果使用SSL验证，也在这里设置。
     *
     * @return factory
     */
    @Bean
    public MqttPahoClientFactory mqttClientFactory() {
        DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory();
        MqttConnectOptions options = new MqttConnectOptions();

        // 设置代理端的URL地址，可以是多个
        options.setServerURIs(new String[]{"tcp://124.222.52.246:1883"});
        options.setUserName("zyt");
        options.setPassword("Zytdsb666".toCharArray());

        factory.setConnectionOptions(options);
        return factory;
    }

    /**
     * 入站通道
     */
    @Bean
    public MessageChannel mqttInputChannel() {
        return new DirectChannel();
    }

    /**
     * 入站
     */
    @Bean
    public MessageProducer inbound() {
        // Paho客户端消息驱动通道适配器，主要用来订阅主题
        MqttPahoMessageDrivenChannelAdapter adapter = new MqttPahoMessageDrivenChannelAdapter("consumerClient_zyt" + Math.random() * 100,
                mqttClientFactory(), "+/", "+/+", "+/+/+", "+/+/+/+");
        adapter.setCompletionTimeout(5000);

        // Paho消息转换器
        DefaultPahoMessageConverter defaultPahoMessageConverter = new DefaultPahoMessageConverter();
        // 按字节接收消息
//        defaultPahoMessageConverter.setPayloadAsBytes(true);
        adapter.setConverter(defaultPahoMessageConverter);
        adapter.setQos(1); // 设置QoS
        adapter.setOutputChannel(mqttInputChannel());
        return adapter;
    }

    @Resource
    private MqttGateway mqttGateway;

    @Bean
    // ServiceActivator注解表明：当前方法用于处理MQTT消息，inputChannel参数指定了用于消费消息的channel。
    @ServiceActivator(inputChannel = "mqttInputChannel")
    public MessageHandler handler() {
        return message -> {
            String payload = message.getPayload().toString();

            // byte[] bytes = (byte[]) message.getPayload(); // 收到的消息是字节格式
            String topic = message.getHeaders().get("mqtt_receivedTopic").toString();
            System.out.println("topic=>" + topic);
            System.out.println("content=>" + payload);

            //如果payload是json数据，则判定其为有效数据，并存储至redis中，有效期为三天
            if (isJson(payload)){
                redisTemplate.opsForValue().set(topic, payload, 3, TimeUnit.DAYS);
            }


            //用正则表达式塞选电力信息,如果是电力信息，则额外存入redis中
            //存放的key为save/power/home_id/room_id
//            if (isPowerTopic(topic)) {
//                timestamp = System.currentTimeMillis() / 1000;
//                Map m = (Map) JSON.parse("payload");
//
//                redisTemplate.boundListOps("save/"+topic).rightPush(m.get("power"));
//
//                //五分钟读取一次redis,存进mysql
//                if (timestamp%300==0){
//
//                    List range = redisTemplate.boundListOps("save/"+topic).range(0, -1);
//
////                    redisTemplate.opsForList().set("save/" + topic, 0,);
//                }
//
//            }


        };
    }

    // 发送消息

    /**
     * 出站通道
     */
    @Bean
    public MessageChannel mqttOutboundChannel() {
        return new DirectChannel();
    }

    /**
     * 出站
     */
    @Bean
    @ServiceActivator(inputChannel = "mqttOutboundChannel")
    public MessageHandler outbound() {

        // 发送消息和消费消息Channel可以使用相同MqttPahoClientFactory
        MqttPahoMessageHandler messageHandler = new MqttPahoMessageHandler("publishClient", mqttClientFactory());
        messageHandler.setAsync(true); // 如果设置成true，即异步，发送消息时将不会阻塞。
        messageHandler.setDefaultTopic("command");
        messageHandler.setDefaultQos(1); // 设置默认QoS

        // Paho消息转换器
        DefaultPahoMessageConverter defaultPahoMessageConverter = new DefaultPahoMessageConverter();

        // defaultPahoMessageConverter.setPayloadAsBytes(true); // 发送默认按字节类型发送消息
        messageHandler.setConverter(defaultPahoMessageConverter);
        return messageHandler;
    }

    public boolean isPowerTopic(String topic) {
        String pattern = "power/[0-9]+/[0-9]+";
        Pattern r = Pattern.compile(pattern);
        Matcher m = r.matcher(topic);
        return m.matches();
    }

    public boolean isJson(String str){
        try {
            Object obj= JSON.parse(str);
            return true;
        } catch (Exception e) {
            return false;
        }
    }
}
